package cn.com.chengmandian.bike.controller.rent;


import cn.com.chengmandian.agent.utils.AuthUtil;
import cn.com.chengmandian.agent.utils.ServletUtil;
import cn.com.chengmandian.bike.dto.RentOrderBikeForm;
import cn.com.chengmandian.bike.dto.RentOrderDto;
import cn.com.chengmandian.bike.dto.RentOrderReletForm;
import cn.com.chengmandian.bike.dto.RentOrderReturnForm;
import cn.com.chengmandian.bike.model.EbDeviceBike;
import cn.com.chengmandian.bike.model.EbRentOrder;
import cn.com.chengmandian.bike.model.EbRentPenalty;
import cn.com.chengmandian.bike.model.vo.RentOrderVo;
import cn.com.chengmandian.bike.service.IEbDeviceBikeService;
import cn.com.chengmandian.bike.service.IEbRentOrderService;
import cn.com.chengmandian.bike.service.IEbRentPenaltyService;
import cn.com.chengmandian.core.common.utils.LnglatUtil;
import cn.com.chengmandian.core.db.pojo.PageData;
import cn.com.chengmandian.core.redis.cache.AgentParamCacheService;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.AjaxResult;
import cn.com.chengmandian.core.web.pojo.BikeAreaParam;
import cn.com.chengmandian.core.web.utils.LocalMapUtil;
import cn.com.chengmandian.service.bike.constants.DeviceCommandEnum;
import cn.com.chengmandian.service.bike.constants.RentOrderStatusEnum;
import cn.com.chengmandian.service.bike.constants.UserTypeEnum;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 电单车运营-分时租赁订单 前端控制器
 * </p>
 *
 * @author AutoGenerator
 * @since 2023-07-10
 */
@Slf4j
@Api(tags = "分时租赁订单")
@RestController
@RequestMapping("/rent/order")
public class EbRentOrderController {

    @Autowired
    private IEbRentOrderService rentOrderService;
    @Autowired
    private IEbDeviceBikeService deviceBikeService;
    @Autowired
    private AgentParamCacheService agentParamCacheService;
    @Autowired
    private IEbRentPenaltyService rentPenaltyService;

    @ApiOperation("我的订单列表")
    @GetMapping("/pages")
    public AjaxResult<PageData<RentOrderVo>> pages(RentOrderDto dto) {
        dto.setMemberId(AuthUtil.getAgentUser().getId());
        if (StrUtil.isNotBlank(dto.getOrderStatus())) {
            dto.setOrderStatusList(Arrays.asList(dto.getOrderStatus().split(",")).stream().map(i -> Integer.parseInt(i)).collect(Collectors.toList()));
        }
        IPage<RentOrderVo> page = rentOrderService.pages(dto);
        if(page.getRecords() != null && ArrayUtil.isAllNotEmpty(page.getRecords())){
            List<RentOrderVo> vos = Collections.synchronizedList(new ArrayList<>());
            for(RentOrderVo vo : page.getRecords()){
                BigDecimal payMoney = vo.getPayMoney();
                if(payMoney == null){
                    payMoney = BigDecimal.ZERO;
                }
                EbRentPenalty rentPenalty = rentPenaltyService.getByOrderId(vo.getId());
                if(rentPenalty != null && rentPenalty.getMoney() != null){
                    vo.setPayMoney(payMoney.add(rentPenalty.getMoney()));
                }
                vos.add(vo);
            }
            page.setRecords(vos);
        }
        return AjaxResult.success(PageData.build(page));
    }

    @ApiOperation("详情")
    @GetMapping("detail/{id}")
    public AjaxResult<RentOrderVo> detail(@PathVariable("id") Integer id){
        return AjaxResult.success(rentOrderService.detail(id));
    }

    @ApiOperation("进行中订单")
    @GetMapping("/running")
    public AjaxResult<RentOrderVo> running(){
        return AjaxResult.success(rentOrderService.getComboRunning(AuthUtil.getAgentUser().getId()));
    }

    @ApiOperation("租赁中订单")
    @GetMapping("/rent")
    public AjaxResult<EbRentOrder> rent() {
        return AjaxResult.success(rentOrderService.getComboRent(AuthUtil.getAgentUser().getId()));
    }

    @ApiOperation("取车")
    @PostMapping("/bike")
    public AjaxResult bike(@RequestBody RentOrderBikeForm form){
        Assert.isTrue(StrUtil.isNotBlank(form.getBikeNo()), "缺少车辆编号");
        Assert.notNull(form.getLng(), "缺少经度");
        Assert.notNull(form.getLat(), "缺少维度");

        Integer memberId = AuthUtil.getAgentUser().getId();
        EbRentPenalty ebRentPenalty = rentPenaltyService.getByMember(memberId);
        if(ebRentPenalty != null){
            throw new BadResponseException(502, "有订单违约金未支付，请先支付违约金", MapUtil.of("orderId", ebRentPenalty.getOrderId()));
        }

        // 租赁订单信息
        EbRentOrder rentOrder = rentOrderService.getStatusOrder(AuthUtil.getAgentUser().getId(), RentOrderStatusEnum.BIKE.getCode());
        Assert.notNull(rentOrder, "未获取到待租赁订单信息");
        // 效验车辆是否可骑行
        EbDeviceBike deviceBike = deviceBikeService.getByNo(form.getBikeNo());
        rentOrderService.checkRentBike(deviceBike);

        BikeAreaParam bikeAreaParam = agentParamCacheService.getParam(deviceBike.getAgentId(), deviceBike.getAreaId());
        if(bikeAreaParam == null || !bikeAreaParam.getUserRideRentEnable()){
            throw new BadResponseException(521, "未开启分时租赁");
        }
        if(ObjectUtil.isNotNull(bikeAreaParam) && ObjectUtil.isNotNull(bikeAreaParam.getUserRideEnable()) && !bikeAreaParam.getUserRideEnable()){
            throw new BadResponseException(514,bikeAreaParam.getUserRideStopNote());
        }

        if (bikeAreaParam.getUserOpenLockDistance() != null && bikeAreaParam.getUserOpenLockDistance() > 0) {
            if(LnglatUtil.getDistance(form.getLng().doubleValue(),
                    form.getLat().doubleValue(),
                    deviceBike.getLng().doubleValue(),
                    deviceBike.getLat().doubleValue()) >= bikeAreaParam.getUserOpenLockDistance()){
                log.error("车辆：{},用户坐标：{},{}，车辆坐标：{},{}", deviceBike.getBikeNo(), form.getLng().doubleValue(), form.getLat().doubleValue(), deviceBike.getLng().doubleValue(), deviceBike.getLat().doubleValue());
                throw new BadResponseException(513,"您的位置必须位于车辆" + bikeAreaParam.getUserOpenLockDistance() + "米范围内");
            }
        }
        // 租赁车辆
        rentOrderService.rentBike(rentOrder, deviceBike, AuthUtil.getAgentUser());
        return AjaxResult.success();
    }

    @ApiOperation("还车")
    @PostMapping("/back")
    public AjaxResult back(@RequestBody RentOrderReturnForm form){
        Assert.notNull(form.getOrderId(), "缺少订单id");

        EbRentOrder rentOrder = rentOrderService.getById(form.getOrderId());
        Assert.isTrue(RentOrderStatusEnum.RENT.getCode().equals(rentOrder.getStatus()), "当前订单已完成，不支持该操作");

        rentOrderService.orderReturn(rentOrder, AuthUtil.getAgentUser(), UserTypeEnum.MEMBER.getCode());
        return AjaxResult.success();
    }

    @ApiOperation("续租")
    @PostMapping("/relet")
    public AjaxResult relet(@RequestBody RentOrderReletForm form) {
        Assert.notNull(form.getComboId(), "请选择套餐");
        Assert.notNull(form.getPayChannel(), "请选择充值渠道");
        return rentOrderService.reletOrder(ServletUtil.getIp(), form, AuthUtil.getAgentUser(), LocalMapUtil.getAgentInfo());
    }

    @ApiOperation("开锁")
    @PostMapping("/open/lock/{id}")
    public AjaxResult open(@PathVariable("id") Integer id){
        rentOrderService.orderSendCommand(id, DeviceCommandEnum.OPEN_LOCK, AuthUtil.getAgentUser(), UserTypeEnum.MEMBER);
        return AjaxResult.success();
    }

    @ApiOperation("关锁")
    @PostMapping("/close/lock/{id}")
    public AjaxResult close(@PathVariable("id")Integer id){
        rentOrderService.orderSendCommand(id, DeviceCommandEnum.STOP_LOCK, AuthUtil.getAgentUser(), UserTypeEnum.MEMBER);
        return AjaxResult.success();
    }

    @ApiOperation("开头盔锁")
    @PostMapping("/open/helmet/{id}")
    public AjaxResult openHelmet(@PathVariable("id") Integer id){
        rentOrderService.orderSendCommand(id, DeviceCommandEnum.OPEN_HELMET, AuthUtil.getAgentUser(), UserTypeEnum.MEMBER);
        return AjaxResult.success();
    }

    @ApiOperation("寻车")
    @PostMapping("/bell/{id}")
    public AjaxResult bell(@PathVariable("id") Integer id){
        rentOrderService.orderSendCommand(id, DeviceCommandEnum.BELL, AuthUtil.getAgentUser(), UserTypeEnum.MEMBER);
        return AjaxResult.success();
    }
}
